/*
 * $Id: ImageExporter.java,v 1.8 2003/06/29 11:15:26 znamenacek Exp $
 *
 * Copyright (c) Milan Jedlicka
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

package net.sf.vofce.export;

import net.sf.vofce.canvas.*;

import java.awt.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;

import org.apache.log4j.Category;

// Canvas
import net.sf.vofce.canvas.*;

import net.sf.vofce.gui.GraphPanel;

// MP
import net.sf.vofce.metapost.*;

// PNG
import com.keypoint.PngEncoder;

// SVG
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.dom.GenericDOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;

// PDF
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;

/**
 * Generates images of graphs. 
 * This class is available in <code>Templates</code>. 
 * Exports graphs in various formats.
 *
 * @author Milan Jedlicka
 */
public class ImageExporter { 

	/** Logger instance. */
	protected static Category logger = Category.getRoot();
	
	/** Width of graph in pixels */
	int pxwidth = 400;

	/** Height of graph in pixels */
	int pxheight = 400;

	/** X axis. */
	protected Axis axisX;

        /** Y axis.  */
	protected Axis axisY;

	/** <code>GraphPanel</code> instance. */
	protected GraphPanel graphPanel = GraphPanel.getInstance();
	
	/** Default constructor */
	public ImageExporter() {
	
	}
	
	/** Sets width of graph in pixels */
	public void setPixelWidth(int pxwidth) {
		this.pxwidth = pxwidth;
	}

	/** Sets height of graph in pixels */
	public void setPixelHeight(int pxheight) {
		this.pxheight = pxheight;
	}
	
	/** @return	width of graph in pixels */
	public int getPixelWidth() {
		return this.pxwidth;
	}

	/** @return	height of graph in pixels */
	public int getPixelHeight() {
		return this.pxheight;	
	}

	/** 
	 * Export to PNG.
	 * @param filename 	the name of file where to file
	 */	
	public void toPNG(String filename) {
		toPNG(new File(filename));
	}

	/** 
	 * Export to PNG. 
	 * @param file 		the <code>File</code> object where to export
	 */	
	public void toPNG(File file) {
		
		BufferedImage image = new BufferedImage((int) pxwidth, (int) pxheight, 1);
                Graphics2D forPNG = image.createGraphics();
		Layer[] layers = graphPanel.getLayers();

		axisX = graphPanel.axisX();
		axisY = graphPanel.axisY();
		
		for (int i = 0; i < layers.length; i++) {
			layers[i].setAxis(axisX, axisY);
                	layers[i].render(forPNG);
		}
		
		byte[] pngbytes;
                PngEncoder png = new PngEncoder( image );
		png.setCompressionLevel(5);

		try {
			FileOutputStream outfile = new FileOutputStream(file);
			pngbytes = png.pngEncode();
			if (pngbytes == null) {
				logger.error("ImageExporter: Null image from PNG encoder.");
			} else {
				outfile.write( pngbytes );
			}
			outfile.flush();
			outfile.close();
		} catch (IOException e) {
			logger.error("ImageExporter: exception while exporting PNG.");
		}
	}

	/** 
	 * Export to SVG.
	 * @param filename 	the name of file where to file
	 */	
	public void toSVG(String filename) {
		toSVG(new File(filename));
	}
	
	/** 
	 * Export to SVG.
	 * @param file 		the <code>File</code> object where to export
	 */	
	public void toSVG(File file) {
	
		DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
	 	Document document = domImpl.createDocument(null, "svg", null);
		SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
		Layer[] layers = graphPanel.getLayers();
	
		axisX = graphPanel.axisX();
		axisY = graphPanel.axisY();
		
		for (int i = 0; i < layers.length; i++) {
			layers[i].setAxis(axisX, axisY);
                	layers[i].render(svgGenerator);
		}
		
	        boolean useCSS = true;
	      
		try {
			FileWriter out = new FileWriter(file);
			svgGenerator.stream(out, useCSS);
		} catch(IOException ioe) {
			logger.error("ImageExporter: exception while exporting SVG.");
		}
		
	}

	/** 
	 * Export to SVG.
	 * @return  the image in SVG format
	 */	
	public String toSVG() {

		DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
	 	Document document = domImpl.createDocument(null, "svg", null);
		SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
		Layer[] layers = graphPanel.getLayers();
	
		axisX = graphPanel.axisX();
		axisY = graphPanel.axisY();
		
		for (int i = 0; i < layers.length; i++) {
			layers[i].setAxis(axisX, axisY);
                	layers[i].render(svgGenerator);
		}
		
	        boolean useCSS = true;

		try {
			StringWriter out = new StringWriter();
			svgGenerator.stream(out, useCSS);
			return out.toString();
		} catch(IOException ioe) {
			logger.error("ImageExporter: exception while exporting SVG.");
		}
		return null;	
	}
	
	
	/** 
	 * Export to SVG for inline use (in template).
	 * @return  the image in SVG without xml definition and DOCTYPE
	 */	
	public String inlineSVG() {
		
	 	DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
	 	Document document = domImpl.createDocument(null, "svg", null);
		SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
		Layer[] layers = graphPanel.getLayers();
	
		axisX = graphPanel.axisX();
		axisY = graphPanel.axisY();
		
		for (int i = 0; i < layers.length; i++) {
			layers[i].setAxis(axisX, axisY);
                	layers[i].render(svgGenerator);
		}
	
	        boolean useCSS = true;

		try {
			StringWriter out = new StringWriter();
			svgGenerator.stream(out, useCSS);
	
			// Filter out xml definition
			String svgOutput = out.toString();		
			
			// Remove xml tag & DOCTYPE tag
			svgOutput = svgOutput.substring(svgOutput.indexOf("\n") + 1, svgOutput.length());
			
			// Remove clear lines
			svgOutput = svgOutput.substring(svgOutput.indexOf("\n") + 1, svgOutput.length());
			
			// Remove DOCTYPE
			svgOutput = svgOutput.substring(svgOutput.indexOf("\n") + 1, svgOutput.length());
			
			return svgOutput;
		} catch(IOException ioe) {
			logger.error("ImageExporter: exception while exporting inline SVG.");
		}
	
		return null;	
	}

	/** 
	 * Export to MetaPost.
	 * @param filename 	the name of file where to file
	 */	
	public void toMP(String filename) {
		toMP(new File(filename));
	}
	
	/** 
	 * Export to MetaPost.
	 * @param file 		the <code>File</code> object where to export
	 */	
	public void toMP(File file) {
		
                Dimension dim = new Dimension(pxwidth, pxheight);
		MPGraphics2D metapostGenerator = new MPGraphics2D(dim);
		metapostGenerator.startExport(file, MPGraphics2D.WHOLE_CONTEXT);
		Layer[] layers = graphPanel.getLayers();

		axisX = graphPanel.axisX();
		axisY = graphPanel.axisY();
		
		for (int i = 0; i < layers.length; i++) {
			layers[i].setAxis(axisX, axisY);
                	layers[i].render(metapostGenerator);
		}
                
		metapostGenerator.endExport();
	}

	/** 
	 * Export to MetaPost.
	 * @return  the image in SVG format
	 */	
	public String toMP() {
                
		Dimension dim = new Dimension(pxwidth, pxheight);
		StringWriter out = new StringWriter();
		Layer[] layers = graphPanel.getLayers();
		MPGraphics2D metapostGenerator = new MPGraphics2D(dim);
		metapostGenerator.startExport(out, MPGraphics2D.WHOLE_CONTEXT);
		
		axisX = graphPanel.axisX();
		axisY = graphPanel.axisY();
		
		for (int i = 0; i < layers.length; i++) {
			layers[i].setAxis(axisX, axisY);
                	layers[i].render(metapostGenerator);
		}
                
		metapostGenerator.endExport();
		return out.toString();
	}		

	/** 
	 * Export to MetaPost for inline use (in template).
	 * @return  the image in MetaPost without header and tail
	 */	
	public String inlineMP() {
                
		Dimension dim = new Dimension(pxwidth, pxheight);
		StringWriter out = new StringWriter();
		MPGraphics2D metapostGenerator = new MPGraphics2D(dim);
		metapostGenerator.startExport(out, MPGraphics2D.IN_LINE_CONTEXT);
		Layer[] layers = graphPanel.getLayers();
	
		axisX = graphPanel.axisX();
		axisY = graphPanel.axisY();
		
		for (int i = 0; i < layers.length; i++) {
			layers[i].setAxis(axisX, axisY);
                	layers[i].render(metapostGenerator);
		}
	
                metapostGenerator.endExport();
		
		return out.toString();
	}

	/** 
	 * Export to PDF.
	 * @param filename 	the name of file where to file
	 */	
	public void toPDF(String filename) {
		toPDF(new File(filename));
	}
	
	/** 
	 * Export to PDF.
	 * @param file 		the <code>File</code> object where to export
	 */	
	public void toPDF(File file) {

		Dimension dim = new Dimension(pxwidth, pxheight);
		Layer[] layers = graphPanel.getLayers();
			
		int w = (int) dim.getWidth();
		int h = (int) dim.getHeight();
		com.lowagie.text.Document document = new com.lowagie.text.Document(new com.lowagie.text.Rectangle(w, h));
	
		try {
			PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
			document.open();
			DefaultFontMapper mapper = new DefaultFontMapper();

			PdfContentByte cb = writer.getDirectContent();

			PdfTemplate tp = cb.createTemplate(w, h);
			Graphics2D g2 = tp.createGraphics(w, h, mapper);
			tp.setWidth(w);
		        tp.setHeight(h);
			
			axisX = graphPanel.axisX();
			axisY = graphPanel.axisY();
			
			for (int i = 0; i < layers.length; i++) {
				layers[i].setAxis(axisX, axisY);
	                	layers[i].render(g2);
			}
	
			g2.dispose();
			cb.addTemplate(tp, 0, 0);
		} catch(Exception e) {
			logger.error("ImageExporter: exception while exporting PDF.");
		}
		document.close();
	}

}
